package com.heze.xunhuan.service.impl;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heze.xunhuan.entity.Message;
import com.heze.xunhuan.entity.User;
import com.heze.xunhuan.exception.BusinessException;
import com.heze.xunhuan.mapper.MessageMapper;
import com.heze.xunhuan.service.MessageService;
import com.heze.xunhuan.service.UserService;
import com.heze.xunhuan.vo.PageVO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 消息服务实现类
 *
 * @author heze-xunhuan
 */
@Service
@RequiredArgsConstructor
public class MessageServiceImpl extends ServiceImpl<MessageMapper, Message> implements MessageService {

    private final UserService userService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createConversation(Long fromUserId, Long toUserId, Long postId, String firstMessage) {
        if (fromUserId.equals(toUserId)) {
            throw new BusinessException(400, "不能与自己创建会话");
        }

        // 检查是否已存在会话
        LambdaQueryWrapper<Message> wrapper = new LambdaQueryWrapper<>();
        wrapper.and(w -> w.eq(Message::getFromUserId, fromUserId).eq(Message::getToUserId, toUserId)
                .or().eq(Message::getFromUserId, toUserId).eq(Message::getToUserId, fromUserId));
        wrapper.orderByDesc(Message::getCreatedAt);
        wrapper.last("LIMIT 1");
        Message lastMessage = this.getOne(wrapper);

        Long conversationId = null;
        if (lastMessage != null) {
            // 使用已有的会话
            conversationId = lastMessage.getId();
        }

        // 发送第一条消息
        if (firstMessage != null && !firstMessage.isEmpty()) {
            sendMessage(fromUserId, toUserId, "text", firstMessage, null, null);
        }

        return conversationId;
    }

    @Override
    public PageVO<Map<String, Object>> getConversations(Long userId, Integer page, Integer size) {
        // 获取用户的所有会话（最后一条消息）
        Page<Message> pageParam = new Page<>(page, size);
        LambdaQueryWrapper<Message> wrapper = new LambdaQueryWrapper<>();
        wrapper.and(w -> w.eq(Message::getFromUserId, userId).or().eq(Message::getToUserId, userId));
        wrapper.orderByDesc(Message::getCreatedAt);

        IPage<Message> messagePage = this.page(pageParam, wrapper);

        // 转换为会话列表
        List<Map<String, Object>> conversations = messagePage.getRecords().stream()
                .map(message -> {
                    Map<String, Object> conversation = new HashMap<>();
                    Long otherUserId = message.getFromUserId().equals(userId) 
                            ? message.getToUserId() 
                            : message.getFromUserId();
                    
                    User otherUser = userService.getById(otherUserId);
                    if (otherUser != null) {
                        Map<String, Object> otherUserInfo = new HashMap<>();
                        otherUserInfo.put("id", otherUser.getId());
                        otherUserInfo.put("nickname", otherUser.getNickname());
                        otherUserInfo.put("avatar", otherUser.getAvatar());
                        conversation.put("otherUser", otherUserInfo);
                    }

                    Map<String, Object> lastMessage = new HashMap<>();
                    lastMessage.put("content", message.getContent());
                    lastMessage.put("messageType", message.getMessageType());
                    lastMessage.put("createdAt", message.getCreatedAt());
                    conversation.put("lastMessage", lastMessage);

                    // 计算未读数量
                    LambdaQueryWrapper<Message> unreadWrapper = new LambdaQueryWrapper<>();
                    unreadWrapper.eq(Message::getFromUserId, otherUserId);
                    unreadWrapper.eq(Message::getToUserId, userId);
                    unreadWrapper.eq(Message::getIsRead, false);
                    long unreadCount = this.count(unreadWrapper);
                    conversation.put("unreadCount", unreadCount);
                    conversation.put("updatedAt", message.getCreatedAt());

                    return conversation;
                })
                .collect(Collectors.toList());

        return new PageVO<>(conversations, page, size, messagePage.getTotal());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long sendMessage(Long fromUserId, Long toUserId, String messageType, String content,
                            String mediaUrl, Map<String, Object> locationInfo) {
        Message message = new Message();
        message.setFromUserId(fromUserId);
        message.setToUserId(toUserId);
        message.setMessageType(messageType);
        message.setContent(content);
        message.setMediaUrl(mediaUrl);
        message.setLocationInfo(locationInfo != null ? JSONUtil.toJsonStr(locationInfo) : null);
        message.setIsRead(false);
        message.setCreatedAt(LocalDateTime.now());

        this.save(message);
        return message.getId();
    }

    @Override
    public PageVO<Message> getMessages(Long conversationId, Long userId, Integer page, Integer size) {
        Message conversation = this.getById(conversationId);
        if (conversation == null) {
            throw new BusinessException(404, "会话不存在");
        }

        // 验证用户是否有权限查看此会话
        if (!conversation.getFromUserId().equals(userId) && !conversation.getToUserId().equals(userId)) {
            throw new BusinessException(403, "无权限查看此会话");
        }

        // 获取会话中的所有消息
        Long otherUserId = conversation.getFromUserId().equals(userId) 
                ? conversation.getToUserId() 
                : conversation.getFromUserId();

        Page<Message> pageParam = new Page<>(page, size);
        LambdaQueryWrapper<Message> wrapper = new LambdaQueryWrapper<>();
        wrapper.and(w -> w.eq(Message::getFromUserId, userId).eq(Message::getToUserId, otherUserId)
                .or().eq(Message::getFromUserId, otherUserId).eq(Message::getToUserId, userId));
        wrapper.orderByDesc(Message::getCreatedAt);

        IPage<Message> messagePage = this.page(pageParam, wrapper);

        // 标记消息为已读
        markAsRead(conversationId, userId);

        return new PageVO<>(messagePage.getRecords(), page, size, messagePage.getTotal());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void markAsRead(Long conversationId, Long userId) {
        Message conversation = this.getById(conversationId);
        if (conversation == null) {
            return;
        }

        Long otherUserId = conversation.getFromUserId().equals(userId) 
                ? conversation.getToUserId() 
                : conversation.getFromUserId();

        LambdaQueryWrapper<Message> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Message::getFromUserId, otherUserId);
        wrapper.eq(Message::getToUserId, userId);
        wrapper.eq(Message::getIsRead, false);

        List<Message> unreadMessages = this.list(wrapper);
        unreadMessages.forEach(message -> {
            message.setIsRead(true);
        });

        if (!unreadMessages.isEmpty()) {
            this.updateBatchById(unreadMessages);
        }
    }
}

